; Disassembly of the file "z:\ramdisk\home\knoppix\none\2716 BOOT 80K EPROM green CoBra.bin"
; 
; CPU Type: Z80
; 
; Created with dZ80 2.0
; 
; on Saturday, 08 of September 2012 at 07:37 PM
;
; Lines containing direct values of video addresses have been marked as *n* where n is a number
; Proper modification of these lines can make the graphic logo work if video RAM is located
; at a different address than C000. In total I found 58 such lines.
;
; Also lines that must to be modified for this code to run relocated have been marked with ---@@@
;
;				############################## START ROUTINE ####################################
;
0000 3E83      LD      A,$83	; bit 7 = "1"
0002 ED4F      LD      R,A	; u36/5 kept at "1" after NPOR="0", so the computer stays in the startup hw config
0004 3173FD    LD      SP,$FD73	; set stack at FD73
0007 2100C0    LD      HL,$C000	; *0* C000 is the start addr for video mem in startup hw configuration (C0->40 @ 0009)
000A 1101C0    LD      DE,$C001	; *1* C001 is the start addr+1 for video mem in startup hw configuration (C0->40 @ 000C)
000D 01FF1A    LD      BC,$1AFF	; 1AFF+1 is the standard total size of Spectrum video memory
0010 3600      LD      (HL),$00	; this will fill up all video memory with zeros when the LDIR below executes
0012 EDB0      LDIR
0014 210000    LD      HL,$0000	; start address of this BOOT EPROM code				---@@@(1)0016:00->10
0017 110080    LD      DE,$8000	; start address of DRAM#0 in the startup config
001A 010008    LD      BC,$0800	; 0800h (2K) is the length of this BOOT EPROM code
001D EDB0      LDIR		; entire BOOT EPROM code is copied from EPROM into DRAM#0
001F 3E03      LD      A,$03	; channel control word for Z80CTC, used in the next 4 instructions:
;				; (Disable Interrupt, Timer mode, Prescaler=16, CLK/TRG Falling Edge,
;				; Auto Trigger, No Time Const. Follows, Reset Channel)
0021 D3E3      OUT     ($E3),A	; reset CTC channel 0
0023 D3EB      OUT     ($EB),A	; reset CTC channel 1
0025 D3F3      OUT     ($F3),A	; reset CTC channel 2
0027 D3FB      OUT     ($FB),A	; reset CTC channel 3
0029 AF        XOR     A	; set A register to "00"
002A D3FD      OUT     ($FD),A	; write "00" to 8272 Data Register (invalid command, places 8272 in standby)
002C 3E92      LD      A,$92	; control word for 8255: Mode Set flag=active,
;				; 			Group A: Select Mode 0,
;				;				 Port A set to Input mode,
;				;				 Port C (upper half) set to Output Mode,
;				;			Group B: Select Mode 0,
;				;				 Port B set to Input Mode,
;				;				 Port C (lower half) set to Output Mode
002E D3DF      OUT     ($DF),A	; write control word to 8255
0030 D3DF      OUT     ($DF),A	; write control word to 8255 (again !?)
0032 3E40      LD      A,$40
0034 D3FE      OUT     ($FE),A	; write 40 to port C of 8255
;				; (set border to black, set signal "SO" to 0, set signal "O5" to 0,
;				;  set signal "O6" to 1 to allow access to video memory in the hw startup config)
0036 181E      JR      $0056	;###################### START ROUTINE CONTINUES AT 0056 #########################
;
;				############################## BASIC CONFIGURATION ##############################
;
0038 210040    LD      HL,$4000	; 4000 is the start addr of BASIC EPROM in the startup hw config
003B 110080    LD      DE,$8000	; 8000 is the start addr of DRAM#0 in the startup hw config
003E 010040    LD      BC,$4000	; 4000 is the length of the SPECTRUM BASIC code (16 KB)
0041 EDB0      LDIR		; copy SPECTRUM BASIC code into DRAM#0
0043 D9        EXX		; (after EXX, HL contains 0000, see line 07F4)
0044 3E03      LD      A,$03	;	SAME AS	]
0046 D3E3      OUT     ($E3),A	;		]
0048 D3EB      OUT     ($EB),A	;	001F	]
004A D3F3      OUT     ($F3),A	;		]
004C D3FB      OUT     ($FB),A	;	 to	]
004E AF        XOR     A	;		]
004F D3FD      OUT     ($FD),A	;	002A	]
0051 D3FE      OUT     ($FE),A	; write 03 to port C of 8255	 <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--|
;				; (set border to white, set signal "SO" to 0, set signal "O5" to 0,				|
;				;  set signal "O6" to 0)									|
0053 ED4F      LD      R,A	; set bit 7 of R to 0, prepare for BASIC hardware configuration					|
0055 E9        JP      (HL)	; change hardware configuration with a jump to (HL)						|
;																|
;				############################# END OF BASIC CONFIGURATION ########################		|
;																|
;				; ###################### START ROUTINE CONTINUED ################################		|
0056 3EFE      LD      A,$FE	; upper half of address bus at I/O time in next instruction (test keyboard row KA8)		|
0058 DBFE      IN      A,($FE)	; read port A of 8255										|
005A CB6F      BIT     5,A	; keyboard test for CTRL key (test keyboard column K5)						|
005C 2033      JR      NZ,$0091	; jump to 0091 if CTRL is not pressed								|
005E AF        XOR     A	; set A to "00" (upper half of address bus at I/O time in next instruction) <--- <--- <-|	|
005F DBFE      IN      A,($FE)	; read port A of 8255 (test keyboard, all rows)						|	|
0061 F640      OR      $40	; set bit 6										|	|
0063 EE20      XOR     $20	; invert bit 5										|	|
0065 D3FE      OUT     ($FE),A	; write result to port C of 8255 (set "O6" to 1, "O5" to 1 - since CTRL is pressed)	|	|
0067 21AA55    LD      HL,$55AA	;											|	|
006A 225515    LD      ($1555),HL	;										|	|
006D 22CC4C    LD      ($4CCC),HL	;										|	|
0070 220F8F    LD      ($8F0F),HL	;										|	|
0073 22FFC0    LD      ($C0FF),HL	;										|	|
0076 2A5515    LD      HL,($1555)	;										|	|
0079 2ACC4C    LD      HL,($4CCC)	;										|	|
007C 2A0F8F    LD      HL,($8F0F)	;										|	|
007F 2AFFC0    LD      HL,($C0FF)	;										|	|
0082 E603      AND     $03	; test bits 0 and 1 (keys "A" and "S")							|	|
0084 20D8      JR      NZ,$005E	; if they are both 1 (keys not pressed), jump back to 005E ---> ---> ---> ---> ---> --->|	|
0086 DBFE      IN      A,($FE)	; read port A of 8255										|
0088 E640      AND     $40	; test bit 6 (Tape Input)									|
008A 215E00    LD      HL,$005E	; set jump address in new config to 005E							|
008D 28C2      JR      Z,$0051	; if Tape Input=0 jump to 0051 ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---->|
008F 18C0      JR      $0051	; jump to 0051 anyway
;
;				######## COBRA GRAPHIC LOGO ###########
;
0091 2100D9    LD      HL,$D900	; *2* video attr start addr for 2nd third of video RAM in startup hw cfg (D9->59 @ 0093)
0094 0608      LD      B,$08
0096 C5        PUSH    BC
0097 01050C    LD      BC,$0C05	; write "05" as color attribute
009A 71        LD      (HL),C	; for the first 12 characters
009B 23        INC     HL	; of the middle third in the
009C 10FC      DJNZ    $009A	; Spectrum screen (INK=cyan, PAPER=black)
009E 010314    LD      BC,$1403	;	write "03" as color attribute
00A1 71        LD      (HL),C	;	for the next 20 characters
00A2 23        INC     HL	;	(INK==white, PAPER=black)
00A3 10FC      DJNZ    $00A1	;	so in total 32 characters (one line)
00A5 C1        POP     BC
00A6 10EE      DJNZ    $0096	; repeat the above 7 times,(all 8 lines in the middle third of screen)
00A8 D9        EXX
00A9 218801    LD      HL,$0188	; HL' used as pointer to data block start address (0188)	---@@@(2)00AB:01->11
00AC D9        EXX
00AD 21B9CB    LD      HL,$CBB9	; *3* address within serial video RAM, middle third of screen (CB->4B @ 00AF)
00B0 11FE01    LD      DE,$01FE	; data to be written in there
00B3 3E04      LD      A,$04
00B5 0609      LD      B,$09
00B7 C5        PUSH    BC	; <--- <--- <--- <--- <--- <--- <--- <--- <--- <---
00B8 47        LD      B,A	;						  |
00B9 72        LD      (HL),D	; write "01" at CBB9 <--- <--- <- <--- <-|	  |
00BA 23        INC     HL	;				|	 |	  |
00BB 73        LD      (HL),E	; write "FE" at CBBA		|	 |	  |
00BC D9        EXX		;				|	 |	  |
00BD 7E        LD      A,(HL)	; read first byte of data (FF)	|	 |	  |
00BE 23        INC     HL	; increment pointer (HL'=0189)	|	 |	  |
00BF D9        EXX		;				|	 |	  |
00C0 4F        LD      C,A	; C = data byte			|	 |	  |
00C1 85        ADD     A,L	; A = data byte + L = B9 + CY	|	 |	  |
00C2 6F        LD      L,A	; L = data byte + L		|	 |	  |
00C3 3001      JR      NC,$00C6	;				|	 |	  |
00C5 24        INC     H	; H=CB+1=CC			|	 |	  |
00C6 10F1      DJNZ    $00B9	; ---> ---> ---> ---> ---> --->>>	 |	  |
00C8 41        LD      B,C	;					 |	  |
00C9 D9        EXX		;					 |	  |
00CA 5E        LD      E,(HL)	; Read 2 bytes				 |	  |
00CB 23        INC     HL	; of data into				 |	  |
00CC 56        LD      D,(HL)	; DE' register.				 |	  |
00CD 23        INC     HL	; Increment pointer			 |	  |
00CE D5        PUSH    DE	;					 |	  |
00CF D9        EXX		;					 |	  |
00D0 E1        POP     HL	; HL = 2 data bytes			 |	  |
00D1 CB23      SLA     E	;					 |	  |
00D3 CB12      RL      D	;					 |	  |
00D5 30E2      JR      NC,$00B9	; ---> ---> ---> ---> ---> ---> ---> --->>	  |
00D7 CB1A      RR      D	;						  |
00D9 CB1B      RR      E	;						  |
00DB 16FF      LD      D,$FF	;						  |
00DD CB22      SLA     D	; <----						  |
00DF CB13      RL      E	;     |						  |
00E1 38FA      JR      C,$00DD	; ---->						  |
00E3 7A        LD      A,D	;						  |
00E4 2F        CPL		;						  |
00E5 57        LD      D,A	;						  |
00E6 1EFF      LD      E,$FF	;						  |
00E8 79        LD      A,C	;						  |
00E9 C1        POP     BC	;						  |
00EA 10CB      DJNZ    $00B7	; ---> ---> ---> ---> ---> ---> ---> ---> ---> --->
00EC 5D        LD      E,L
00ED 54        LD      D,H
00EE D9        EXX
00EF E5        PUSH    HL
00F0 D9        EXX
00F1 E1        POP     HL
00F2 060B      LD      B,$0B
00F4 C5        PUSH    BC	; <--- <---
00F5 47        LD      B,A	;	  |
00F6 7E        LD      A,(HL)	;	  |
00F7 23        INC     HL	;	  |
00F8 12        LD      (DE),A	; <----   |
00F9 13        INC     DE	;     |   |
00FA 10FC      DJNZ    $00F8	; ---->   |
00FC 7E        LD      A,(HL)	;	  |
00FD 23        INC     HL	;	  |
00FE 5E        LD      E,(HL)	;	  |
00FF 23        INC     HL	;	  |
0100 56        LD      D,(HL)	;	  |
0101 23        INC     HL	;	  |
0102 C1        POP     BC	;	  |
0103 10EF      DJNZ    $00F4	; ---> --->
0105 21E003    LD      HL,$03E0	; addr of color attr for color pattern under logo (within data block)	---@@@(3)0107:03->13
0108 118CDA    LD      DE,$DA8C	; *4* addr of color attr for color pattern under logo (within video mem) (DA->5A @ 010A)
010B 010800    LD      BC,$0008	; length of color pattern under logo
010E EDB0      LDIR
0110 1607      LD      D,$07	; ######### BEGINNING OF ONE SCREEN CYCLE (KBD READ + SCROLL LEFT) #########
0112 010000    LD      BC,$0000
0115 3E78      LD      A,$78	; keyboard test, rows KA15 ("B" key), KA10 ("W" key), KA9 ("D" key), KA8 ("C" key)
0117 DBFE      IN      A,($FE)
0119 1F        RRA
011A 1F        RRA
011B D2F407    JP      NC,$07F4	; if "W" pressed, jump to OPUS loading routine			---@@@(4)011D:07->17
011E 1F        RRA
011F D25205    JP      NC,$0552	; if "D" pressed, jump to CP/M loading routine			---@@@(5)0121:05->15
0122 1F        RRA
0123 D23705    JP      NC,$0537	; if "C" pressed, jump to tape loading routine			---@@@(6)0125:05->15
0126 1F        RRA
0127 D2F007    JP      NC,$07F0	; if "B" pressed, jump to BASIC loading routine			---@@@(7)0129:07->17
012A 1F        RRA
012B D29704    JP      NC,$0497	; if "F4" or "CTRL" pressed, jump to checksum routine		---@@@(8)012D:04->14
012E 10E5      DJNZ    $0115	; cycle the above 256 times
0130 0D        DEC     C
0131 20E2      JR      NZ,$0115	; cycle the above 256 times (65536 times total)
0133 15        DEC     D
0134 20DF      JR      NZ,$0115	; cycle the above 7 times (458752 times total)
0136 0620      LD      B,$20
0138 C5        PUSH    BC	; BC=2000
0139 CD5901    CALL    $0159	; call SERIAL VIDEO GRAPHIC SCROLL LEFT 4 PIXELS		---@@@(9)013B:01->11
013C 2101D9    LD      HL,$D901	; *5* video attr start addr for 2nd third of video RAM in startup hw cfg (D9->59 @ 013E)
013F 0608      LD      B,$08	; 	  ######## 00D5-00E7 mid screen attribute scroll left 1 char ########
0141 C5        PUSH    BC	; BC=0800 (B=08 used as row counter)    <--- <--- <--- <--- <---|
0142 011F00    LD      BC,$001F	; screen width in chars minus 1					|
0145 54        LD      D,H	;								|
0146 5D        LD      E,L	; DE=D901							|
0147 1D        DEC     E	; DE=D900 (start of row 1 (of 8) of attr's for middle third of screen)
0148 1A        LD      A,(DE)	; copy the first attr byte on the row				|
0149 EDB0      LDIR		; shift 31 attribute bytes left, first byte overwritten		|
014B 12        LD      (DE),A	; save the former first byte into the last on the row		|
014C 2C        INC     L	; HL now points to first char on next row			|
014D 1C        INC     E	; DE now points to last char on row				|
014E C1        POP     BC	; POP back the row counter					|
014F 10F0      DJNZ    $0141	; ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ->|    ########
0151 CD5901    CALL    $0159	; call SERIAL VIDEO GRAPHIC SCROLL LEFT 4 PIXELS		---@@@(10)0153:01->11
0154 C1        POP     BC
0155 10E1      DJNZ    $0138
0157 18B7      JR      $0110	; ###### END COBRA GRAPHIC LOGO ROUTINE #########

0159 0604      LD      B,$04	; ######## SERIAL VIDEO GRAPHIC SCROLL LEFT 4 PIXELS ########
015B C5        PUSH    BC
015C 21FFCF    LD      HL,$CFFF	; *6* address within video memory (CF->4F @ 015E)
015F 0608      LD      B,$08
0161 C5        PUSH    BC
0162 0608      LD      B,$08
0164 C5        PUSH    BC
0165 54        LD      D,H
0166 5D        LD      E,L
0167 0620      LD      B,$20
0169 37        SCF
016A CB16      RL      (HL)
016C 2B        DEC     HL
016D 10FB      DJNZ    $016A
016F 3803      JR      C,$0174
0171 1A        LD      A,(DE)
0172 3D        DEC     A
0173 12        LD      (DE),A
0174 C1        POP     BC
0175 B7        OR      A
0176 11E000    LD      DE,$00E0
0179 ED52      SBC     HL,DE
017B 10E7      DJNZ    $0164
017D 01E007    LD      BC,$07E0
0180 09        ADD     HL,BC
0181 C1        POP     BC
0182 10DD      DJNZ    $0161
0184 C1        POP     BC
0185 10D4      DJNZ    $015B
0187 C9        RET		; ######## SERIAL VIDEO GRAPHIC SCROLL LEFT 4 PIXELS END #############

0188 FF        DB      $FF	; ############## GRAPHIC DATA BLOCK ################
0189 E0        DB      $E0
018A FF        DB      $FF
018B 1F        DB      $1F
018C B1        DB      $B1
018D C8        DB      $C8	; *7*	(C8->48)
018E 45        DB      $45
018F B9        DB      $B9
0190 22        DB      $22
0191 02        DB      $02
0192 1F        DB      $1F
0193 A2        DB      $A2
0194 16        DB      $16
0195 22        DB      $22
0196 02        DB      $02
0197 1F        DB      $1F
0198 A2        DB      $A2
0199 16        DB      $16
019A 25        DB      $25
019B 15        DB      $15
019C 09        DB      $09
019D 75        DB      $75
019E 43        DB      $43
019F 25        DB      $25
01A0 BC        DB      $BC
01A1 02        DB      $02
01A2 19        DB      $19
01A3 25        DB      $25
01A4 BC        DB      $BC
01A5 02        DB      $02
01A6 19        DB      $19
01A7 07        DB      $07
01A8 1D        DB      $1D
01A9 D9        DB      $D9
01AA 07        DB      $07
01AB 1D        DB      $1D
01AC 0C        DB      $0C
01AD 9A        DB      $9A
01AE C8        DB      $C8	; *8*	(C8->48)
01AF 07        DB      $07
01B0 A5        DB      $A5
01B1 90        DB      $90
01B2 FF        DB      $FF
01B3 88        DB      $88
01B4 FF        DB      $FF
01B5 E5        DB      $E5
01B6 FF        DB      $FF
01B7 FF        DB      $FF
01B8 31        DB      $31
01B9 07        DB      $07
01BA 0C        DB      $0C
01BB 82        DB      $82
01BC C8        DB      $C8	; *9*	(C8->48)
01BD FF        DB      $FF
01BE FF        DB      $FF
01BF FF        DB      $FF
01C0 6D        DB      $6D
01C1 7F        DB      $7F
01C2 09        DB      $09
01C3 07        DB      $07
01C4 F7        DB      $F7
01C5 07        DB      $07
01C6 DF        DB      $DF
01C7 FF        DB      $FF
01C8 09        DB      $09
01C9 CC        DB      $CC
01CA C8        DB      $C8	; *10*	(C8->48)
01CB 7B        DB      $7B
01CC 92        DB      $92
01CD FF        DB      $FF
01CE FF        DB      $FF
01CF EB        DB      $EB
01D0 FF        DB      $FF
01D1 FF        DB      $FF
01D2 C4        DB      $C4
01D3 10        DB      $10
01D4 AF        DB      $AF
01D5 C8        DB      $C8	; *11*	(C8->48)
01D6 FC        DB      $FC
01D7 02        DB      $02
01D8 FC        DB      $FC
01D9 02        DB      $02
01DA FC        DB      $FC
01DB 02        DB      $02
01DC FC        DB      $FC
01DD 02        DB      $02
01DE FC        DB      $FC
01DF 02        DB      $02
01E0 FC        DB      $FC
01E1 02        DB      $02
01E2 0B        DB      $0B
01E3 F3        DB      $F3
01E4 0B        DB      $0B
01E5 06        DB      $06
01E6 87        DB      $87
01E7 C8        DB      $C8	; *12*	(C8->48)
01E8 C0        DB      $C0
01E9 FF        DB      $FF
01EA FF        DB      $FF
01EB 72        DB      $72
01EC FF        DB      $FF
01ED 0B        DB      $0B
01EE 46        DB      $46
01EF C8        DB      $C8	; *13*	(C8->48)
01F0 74        DB      $74
01F1 6E        DB      $6E
01F2 3D        DB      $3D
01F3 52        DB      $52
01F4 8E        DB      $8E
01F5 9F        DB      $9F
01F6 FE        DB      $FE
01F7 DD        DB      $DD
01F8 FF        DB      $FF
01F9 82        DB      $82
01FA 11        DB      $11
01FB 8C        DB      $8C
01FC C8        DB      $C8	; *14*	(C8->48)
01FD 62        DB      $62
01FE 55        DB      $55
01FF 20        DB      $20
0200 E1        DB      $E1
0201 70        DB      $70
0202 8E        DB      $8E
0203 DA        DB      $DA
0204 A3        DB      $A3
0205 7A        DB      $7A
0206 5F        DB      $5F
0207 9F        DB      $9F
0208 5F        DB      $5F
0209 CC        DB      $CC
020A 2A        DB      $2A
020B 28        DB      $28
020C 08        DB      $08
020D 0B        DB      $0B
020E 62        DB      $62
020F C8        DB      $C8	; *15*	(C8->48)
0210 E5        DB      $E5
0211 FF        DB      $FF
0212 FF        DB      $FF
0213 59        DB      $59
0214 F7        DB      $F7
0215 07        DB      $07
0216 A5        DB      $A5
0217 70        DB      $70
0218 B6        DB      $B6
0219 D1        DB      $D1
021A 13        DB      $13
021B D1        DB      $D1
021C C8        DB      $C8	; *16*	(C8->48)
021D 02        DB      $02
021E 02        DB      $02
021F 01        DB      $01
0220 88        DB      $88
0221 37        DB      $37
0222 07        DB      $07
0223 2E        DB      $2E
0224 90        DB      $90
0225 3F        DB      $3F
0226 A5        DB      $A5
0227 8B        DB      $8B
0228 BF        DB      $BF
0229 02        DB      $02
022A F9        DB      $F9
022B FF        DB      $FF
022C FF        DB      $FF
022D 02        DB      $02
022E 02        DB      $02
022F 08        DB      $08
0230 D1        DB      $D1
0231 CA        DB      $CA	; *17*	(CA->4A)
0232 76        DB      $76
0233 90        DB      $90
0234 ED        DB      $ED
0235 9A        DB      $9A
0236 2E        DB      $2E
0237 E8        DB      $E8
0238 07        DB      $07
0239 09        DB      $09
023A CC        DB      $CC
023B C9        DB      $C9	; *18*	(C9->49)
023C 7B        DB      $7B
023D 86        DB      $86
023E 78        DB      $78
023F 92        DB      $92
0240 EB        DB      $EB
0241 9F        DB      $9F
0242 27        DB      $27
0243 FC        DB      $FC
0244 0B        DB      $0B
0245 AC        DB      $AC
0246 C8        DB      $C8	; *19*	(C8->48)
0247 22        DB      $22
0248 0B        DB      $0B
0249 F3        DB      $F3
024A FC        DB      $FC
024B FF        DB      $FF
024C FA        DB      $FA
024D FF        DB      $FF
024E C7        DB      $C7
024F FF        DB      $FF
0250 1C        DB      $1C
0251 03        DB      $03
0252 BB        DB      $BB
0253 CD        DB      $CD	; *20*	(CD->4D)
0254 B4        DB      $B4
0255 F6        DB      $F6
0256 10        DB      $10
0257 2A        DB      $2A
0258 C8        DB      $C8	; *21*	(C8->48)
0259 C6        DB      $C6
025A 54        DB      $54
025B 03        DB      $03
025C FD        DB      $FD
025D 72        DB      $72
025E 38        DB      $38
025F F5        DB      $F5
0260 DC        DB      $DC
0261 7B        DB      $7B
0262 30        DB      $30
0263 02        DB      $02
0264 F8        DB      $F8
0265 32        DB      $32
0266 A6        DB      $A6
0267 26        DB      $26
0268 0C        DB      $0C
0269 66        DB      $66
026A C8        DB      $C8	; *22*	(C8->48)
026B 28        DB      $28
026C FC        DB      $FC
026D BB        DB      $BB
026E FF        DB      $FF
026F DE        DB      $DE
0270 FB        DB      $FB
0271 E4        DB      $E4
0272 BA        DB      $BA
0273 08        DB      $08
0274 FA        DB      $FA
0275 07        DB      $07
0276 01        DB      $01
0277 46        DB      $46
0278 CF        DB      $CF	; *23*	(CF->4F)
0279 01        DB      $01
027A 46        DB      $46
027B CE        DB      $CE	; *24*	(CE->4E)
027C 05        DB      $05
027D CC        DB      $CC
027E CA        DB      $CA	; *25*	(CA->4A)
027F FF        DB      $FF
0280 FA        DB      $FA
0281 7E        DB      $7E
0282 45        DB      $45
0283 01        DB      $01
0284 46        DB      $46
0285 CC        DB      $CC	; *26*	(CC->4C)
0286 01        DB      $01
0287 46        DB      $46
0288 CB        DB      $CB	; *27*	(CB->4B)
0289 0C        DB      $0C
028A 91        DB      $91
028B C8        DB      $C8	; *28*	(C8->48)
028C B6        DB      $B6
028D FD        DB      $FD
028E E1        DB      $E1
028F 9B        DB      $9B
0290 7E        DB      $7E
0291 85        DB      $85
0292 FD        DB      $FD
0293 FF        DB      $FF
0294 61        DB      $61
0295 79        DB      $79
0296 2D        DB      $2D
0297 0A        DB      $0A
0298 24        DB      $24
0299 C9        DB      $C9	; *29*	(C9->49)
029A 6A        DB      $6A
029B FC        DB      $FC
029C 57        DB      $57
029D EC        DB      $EC
029E F5        DB      $F5
029F FB        DB      $FB
02A0 08        DB      $08
02A1 56        DB      $56
02A2 AB        DB      $AB
02A3 02        DB      $02
02A4 CC        DB      $CC
02A5 CB        DB      $CB	; *30*	(CB->4B)
02A6 BF        DB      $BF
02A7 04        DB      $04
02A8 ED        DB      $ED
02A9 CA        DB      $CA	; *31*	(CA->4A)
02AA E1        DB      $E1
02AB BF        DB      $BF
02AC DD        DB      $DD
02AD 03        DB      $03
02AE D1        DB      $D1
02AF CB        DB      $CB	; *32*	(CB->4B)
02B0 95        DB      $95
02B1 29        DB      $29
02B2 01        DB      $01
02B3 E6        DB      $E6
02B4 C8        DB      $C8
02B5 0D        DB      $0D
02B6 C3        DB      $C3
02B7 C8        DB      $C8	; *33*	(C8->48)
02B8 CD        DB      $CD
02B9 62        DB      $62
02BA F3        DB      $F3
02BB 5A        DB      $5A
02BC E3        DB      $E3
02BD FF        DB      $FF
02BE A1        DB      $A1
02BF 40        DB      $40
02C0 1E        DB      $1E
02C1 4A        DB      $4A
02C2 02        DB      $02
02C3 59        DB      $59
02C4 0D        DB      $0D
02C5 8F        DB      $8F
02C6 CA        DB      $CA	; *34*	(CA->4A)
02C7 FC        DB      $FC
02C8 02        DB      $02
02C9 97        DB      $97
02CA 9B        DB      $9B
02CB 08        DB      $08
02CC 02        DB      $02
02CD 09        DB      $09
02CE F5        DB      $F5
02CF 09        DB      $09
02D0 2A        DB      $2A
02D1 62        DB      $62
02D2 BB        DB      $BB
02D3 01        DB      $01
02D4 E6        DB      $E6
02D5 C8        DB      $C8
02D6 04        DB      $04
02D7 F0        DB      $F0
02D8 CA        DB      $CA	; *35*	(CA->4A)
02D9 F8        DB      $F8
02DA DD        DB      $DD
02DB A8        DB      $A8
02DC 02        DB      $02
02DD C3        DB      $C3
02DE C9        DB      $C9	; *36*	(C9->49)
02DF 7F        DB      $7F
02E0 14        DB      $14
02E1 94        DB      $94
02E2 C8        DB      $C8	; *37*	(C8->48) !!
02E3 02        DB      $02
02E4 5C        DB      $5C
02E5 FB        DB      $FB
02E6 A0        DB      $A0
02E7 FF        DB      $FF
02E8 22        DB      $22
02E9 02        DB      $02
02EA 52        DB      $52
02EB A9        DB      $A9
02EC 02        DB      $02
02ED 19        DB      $19
02EE 09        DB      $09
02EF 4D        DB      $4D
02F0 A7        DB      $A7
02F1 09        DB      $09
02F2 ED        DB      $ED
02F3 AA        DB      $AA
02F4 02        DB      $02
02F5 5C        DB      $5C
02F6 0C        DB      $0C
02F7 43        DB      $43
02F8 C8        DB      $C8	; *38*	(C8->48)
02F9 B5        DB      $B5
02FA EA        DB      $EA
02FB 3F        DB      $3F
02FC E3        DB      $E3
02FD BA        DB      $BA
02FE 40        DB      $40
02FF C2        DB      $C2
0300 FF        DB      $FF
0301 FF        DB      $FF
0302 11        DB      $11
0303 FF        DB      $FF
0304 07        DB      $07
0305 43        DB      $43
0306 C9        DB      $C9	; *39*	(C9->49)
0307 E4        DB      $E4
0308 9A        DB      $9A
0309 84        DB      $84
030A AA        DB      $AA
030B 7F        DB      $7F
030C 02        DB      $02
030D 07        DB      $07
030E ED        DB      $ED
030F C9        DB      $C9	; *40*	(C9->49)
0310 FA        DB      $FA
0311 7E        DB      $7E
0312 BF        DB      $BF
0313 FF        DB      $FF
0314 FF        DB      $FF
0315 45        DB      $45
0316 17        DB      $17
0317 26        DB      $26
0318 C8        DB      $C8	; *41*	(C8->48) !!
0319 D4        DB      $D4
031A 98        DB      $98
031B 02        DB      $02
031C 1C        DB      $1C
031D 02        DB      $02
031E DC        DB      $DC
031F 02        DB      $02
0320 1C        DB      $1C
0321 02        DB      $02
0322 52        DB      $52
0323 FD        DB      $FD
0324 20        DB      $20
0325 FD        DB      $FD
0326 8C        DB      $8C
0327 02        DB      $02
0328 1C        DB      $1C
0329 DF        DB      $DF
032A 02        DB      $02
032B 1C        DB      $1C
032C 06        DB      $06
032D ED        DB      $ED
032E 11        DB      $11
032F 2A        DB      $2A
0330 28        DB      $28
0331 C8        DB      $C8	; *42*	(C8->48) !!
0332 6A        DB      $6A
0333 02        DB      $02
0334 1C        DB      $1C
0335 02        DB      $02
0336 3C        DB      $3C
0337 9F        DB      $9F
0338 02        DB      $02
0339 1C        DB      $1C
033A 02        DB      $02
033B 3C        DB      $3C
033C 05        DB      $05
033D 99        DB      $99
033E 02        DB      $02
033F 1C        DB      $1C
0340 02        DB      $02
0341 3C        DB      $3C
0342 05        DB      $05
0343 0A        DB      $0A
0344 8E        DB      $8E
0345 02        DB      $02
0346 1C        DB      $1C
0347 02        DB      $02
0348 42        DB      $42
0349 B9        DB      $B9
034A 02        DB      $02
034B 1C        DB      $1C
034C 9F        DB      $9F
034D 02        DB      $02
034E 3C        DB      $3C
034F 02        DB      $02
0350 1C        DB      $1C
0351 9F        DB      $9F
0352 02        DB      $02
0353 3C        DB      $3C
0354 02        DB      $02
0355 1C        DB      $1C
0356 9F        DB      $9F
0357 02        DB      $02
0358 3C        DB      $3C
0359 02        DB      $02
035A 1C        DB      $1C
035B 01        DB      $01
035C E6        DB      $E6
035D C8        DB      $C8
035E 17        DB      $17
035F 8D        DB      $8D
0360 C8        DB      $C8	; *43*	(C8->48) !!
0361 26        DB      $26
0362 02        DB      $02
0363 31        DB      $31
0364 03        DB      $03
0365 38        DB      $38
0366 66        DB      $66
0367 6D        DB      $6D
0368 91        DB      $91
0369 6D        DB      $6D
036A 2D        DB      $2D
036B 63        DB      $63
036C 06        DB      $06
036D 02        DB      $02
036E 63        DB      $63
036F D1        DB      $D1
0370 06        DB      $06
0371 F8        DB      $F8
0372 FF        DB      $FF
0373 9F        DB      $9F
0374 46        DB      $46
0375 02        DB      $02
0376 15        DB      $15
0377 06        DB      $06
0378 25        DB      $25
0379 C8        DB      $C8	; *44*	(C8->48)
037A BE        DB      $BE
037B 43        DB      $43
037C FF        DB      $FF
037D FB        DB      $FB
037E C0        DB      $C0
037F 08        DB      $08
0380 E9        DB      $E9
0381 C9        DB      $C9	; *45*	(C9->49)
0382 3C        DB      $3C
0383 02        DB      $02
0384 3D        DB      $3D
0385 E1        DB      $E1
0386 DD        DB      $DD
0387 9D        DB      $9D
0388 83        DB      $83
0389 29        DB      $29
038A E6        DB      $E6
038B C8        DB      $C8	; *46*	(C8->48) !!
038C 01        DB      $01
038D 5F        DB      $5F
038E 9D        DB      $9D
038F 01        DB      $01
0390 07        DB      $07
0391 37        DB      $37
0392 1F        DB      $1F
0393 9D        DB      $9D
0394 01        DB      $01
0395 1D        DB      $1D
0396 01        DB      $01
0397 1D        DB      $1D
0398 01        DB      $01
0399 1F        DB      $1F
039A 9E        DB      $9E
039B 01        DB      $01
039C 1C        DB      $1C
039D 01        DB      $01
039E 1C        DB      $1C
039F 01        DB      $01
03A0 9D        DB      $9D
03A1 01        DB      $01
03A2 5D        DB      $5D
03A3 01        DB      $01
03A4 20        DB      $20
03A5 7C        DB      $7C
03A6 01        DB      $01
03A7 3E        DB      $3E
03A8 01        DB      $01
03A9 1C        DB      $1C
03AA 01        DB      $01
03AB 20        DB      $20
03AC 27        DB      $27
03AD 54        DB      $54
03AE 01        DB      $01
03AF 5D        DB      $5D
03B0 01        DB      $01
03B1 20        DB      $20
03B2 7C        DB      $7C
03B3 01        DB      $01
03B4 01        DB      $01
03B5 45        DB      $45
03B6 C8        DB      $C8	; *47*	(C8->48)
03B7 C3        DB      $C3
03B8 01        DB      $01
03B9 87        DB      $87
03BA C8        DB      $C8	; *48*	(C8->48)
03BB 03        DB      $03
03BC 01        DB      $01
03BD 87        DB      $87
03BE C9        DB      $C9	; *49*	(C9->49)
03BF 01        DB      $01
03C0 01        DB      $01
03C1 68        DB      $68
03C2 CE        DB      $CE	; *50*	(CE->4E)
03C3 E0        DB      $E0
03C4 01        DB      $01
03C5 67        DB      $67
03C6 CF        DB      $CF	; *51*	(CF->4F)
03C7 07        DB      $07
03C8 0A        DB      $0A
03C9 03        DB      $03
03CA D9        DB      $D9	; *52*	(D9->59)	BLUE CROWN
03CB 01        DB      $01
03CC 02        DB      $02
03CD 27        DB      $27
03CE D9        DB      $D9	; *53*	(D9->59)	YELLOW EYE
03CF 35        DB      $35
03D0 01        DB      $01
03D1 47        DB      $47
03D2 D9        DB      $D9	; *54*	(D9->59)	RED MOUTH
03D3 15        DB      $15
03D4 04        DB      $04
03D5 48        DB      $48
03D6 D9        DB      $D9	; *55*	(D9->59)	RED TONGUE
03D7 02        DB      $02
03D8 01        DB      $01
03D9 8B        DB      $8B
03DA D9        DB      $D9	; *56*	(D9->59)
03DB 03        DB      $03
03DC 01        DB      $01
03DD AB        DB      $AB
03DE D9        DB      $D9	; *57*	(D9->59)
03DF 03        DB      $03
03E0 07        DB      $07
03E1 0E        DB      $0E
03E2 15        DB      $15
03E3 1C        DB      $1C
03E4 23        DB      $23
03E5 2A        DB      $2A
03E6 31        DB      $31
03E7 38        DB      $38	; ################ END OF GRAPHIC BLOCK ################

03E8 3EFE      LD      A,$FE	; SUBROUTINE USED BY THE TAPE LOADING ROUTINE
03EA 110020    LD      DE,$2000
03ED 14        INC     D
03EE 08        EX      AF,AF'
03EF 15        DEC     D
03F0 3E4F      LD      A,$4F
03F2 D3FE      OUT     ($FE),A
03F4 DBFE      IN      A,($FE)
03F6 1F        RRA
03F7 E620      AND     $20
03F9 F602      OR      $02
03FB 4F        LD      C,A
03FC BF        CP      A
03FD C0        RET     NZ

03FE CD7904    CALL    $0479	;								---@@@(11)0400:04->14
0401 30FA      JR      NC,$03FD
0403 211504    LD      HL,$0415
0406 10FE      DJNZ    $0406
0408 2B        DEC     HL
0409 7C        LD      A,H
040A B5        OR      L
040B 20F9      JR      NZ,$0406
040D CD7504    CALL    $0475	;								---@@@(12)040F:04->14
0410 30EB      JR      NC,$03FD
0412 069C      LD      B,$9C
0414 CD7504    CALL    $0475	;								---@@@(13)0416:04->14
0417 30E4      JR      NC,$03FD
0419 3EC6      LD      A,$C6
041B B8        CP      B
041C 30E0      JR      NC,$03FE
041E 24        INC     H
041F 20F1      JR      NZ,$0412
0421 06C9      LD      B,$C9
0423 CD7904    CALL    $0479	;								---@@@(14)0425:04->14
0426 30D5      JR      NC,$03FD
0428 78        LD      A,B
0429 FED4      CP      $D4
042B 30F4      JR      NC,$0421
042D CD7904    CALL    $0479	;								---@@@(15)042F:04->14
0430 D0        RET     NC

0431 79        LD      A,C
0432 EE03      XOR     $03
0434 4F        LD      C,A
0435 2600      LD      H,$00
0437 06B0      LD      B,$B0
0439 181F      JR      $045A
043B 08        EX      AF,AF'
043C 2007      JR      NZ,$0445
043E 300F      JR      NC,$044F
0440 DD7500    LD      (IX+$00),L
0443 180F      JR      $0454
0445 CB11      RL      C
0447 AD        XOR     L
0448 C0        RET     NZ

0449 79        LD      A,C
044A 1F        RRA
044B 4F        LD      C,A
044C 13        INC     DE
044D 1807      JR      $0456
044F DD7E00    LD      A,(IX+$00)
0452 AD        XOR     L
0453 C0        RET     NZ

0454 DD23      INC     IX
0456 1B        DEC     DE
0457 08        EX      AF,AF'
0458 06B2      LD      B,$B2
045A 2E01      LD      L,$01
045C CD7504    CALL    $0475	;								---@@@(16)045E:04->14
045F D0        RET     NC

0460 3ECB      LD      A,$CB
0462 B8        CP      B
0463 CB15      RL      L
0465 06B0      LD      B,$B0
0467 D25C04    JP      NC,$045C	;								---@@@(17)0469:04->14
046A 7C        LD      A,H
046B AD        XOR     L
046C 67        LD      H,A
046D 7A        LD      A,D
046E B3        OR      E
046F 20CA      JR      NZ,$043B
0471 7C        LD      A,H
0472 FE01      CP      $01
0474 C9        RET		; END SUBROUTINE USED BY TAPE LOADING ROUTINE

0475 CD7904    CALL    $0479	; SUBROUTINE USED BY THE ABOVE					---@@@(18)0477:04->14
0478 D0        RET     NC

0479 3E16      LD      A,$16
047B 3D        DEC     A
047C 20FD      JR      NZ,$047B
047E A7        AND     A
047F 04        INC     B
0480 C8        RET     Z

0481 3E7F      LD      A,$7F
0483 DBFE      IN      A,($FE)
0485 1F        RRA
0486 D0        RET     NC

0487 A9        XOR     C
0488 E620      AND     $20
048A 28F3      JR      Z,$047F
048C 79        LD      A,C
048D 2F        CPL
048E 4F        LD      C,A
048F E607      AND     $07
0491 F648      OR      $48
0493 D3FE      OUT     ($FE),A
0495 37        SCF
0496 C9        RET		; END SUBROUTINE USED BY THE ABOVE

0497 3E01      LD      A,$01	; ############## START CHECKSUM ROUTINE ################
0499 D3FE      OUT     ($FE),A	; set "O6" to 0, CPU access to DRAM#1 instead of VRAM
049B 21AF04    LD      HL,$04AF	; address of code block below					---@@@(19)049D:04->14
049E 1100E0    LD      DE,$E000	; beginning of upper half of DRAM#1 (6000 in BASIC config)
04A1 011700    LD      BC,$0017
04A4 EDB0      LDIR		; copy code block to beginning of upper half of DRAM#1
04A6 3E41      LD      A,$41
04A8 D3FE      OUT     ($FE),A	; set "O6" to 1, CPU access to VRAM instead of DRAM#1
04AA 210060    LD      HL,$6000
04AD 181A      JR      $04C9
				; ######## code block ########
				; this block is copied to E000h, and after loading OPUS (BASIC clears the memory)
				; will be available at 6000h. If then run (using the command
				; "E 6000" in monitor mode) it will save the OPUS code in two 8KB blocks.
04AF DD210000  LD      IX,$0000
04B3 DDE5      PUSH    IX	; 0000 is the return addr after calling this routine (reset OPUS)
04B5 CD0D60    CALL    $600D	; this calls the entry point below
04B8 DD210020  LD      IX,$2000
04BC 110020    LD      DE,$2000	; entry point (6000 in BASIC/OPUS config)
04BF 3EFE      LD      A,$FE
04C1 37        SCF
04C2 CDC204    CALL    $04C2	; start of SAVE routine in BASIC (also exactly THIS address !!)
04C5 C9        RET		; ######## end code block #########

04C6 210000    LD      HL,$0000
04C9 E5        PUSH    HL
04CA 0608      LD      B,$08	; loop counter
04CC 210040    LD      HL,$4000
04CF FD21F007  LD      IY,$07F0	; start of BASIC LOAD code and also BASIC checksum data		---@@@(20)04D2:07->17
04D3 DD218CDA  LD      IX,$DA8C	; addr of color attr for color pattern under logo (within video mem)
04D7 DDCB00FE  SET     7,(IX+$00) ; set BLINK attribute for first cell of color pattern <--- <--|
04DB C5        PUSH    BC	;								|
04DC 110008    LD      DE,$0800	;								|
04DF D9        EXX		;								|
04E0 210000    LD      HL,$0000	;								|
04E3 D9        EXX		;								|
04E4 7E        LD      A,(HL)	; <--- <--- <--- <--- <--- <--- | read from (4000)		|
04E5 D9        EXX		;				|				|
04E6 0608      LD      B,$08	; loop counter			|				|
04E8 4F        LD      C,A	;				|				|
04E9 CB01      RLC     C	; CY = bit 7<--- <--- <---|	|				|
04EB 9F        SBC     A,A	; A=00-CY		  |	|				|
04EC 5F        LD      E,A	;			  |	|				|
04ED 7D        LD      A,L	; (loop starts w HL=0000) |	|				|
04EE E640      AND     $40	;			  |	|				|
04F0 D601      SUB     $01	;			  |	|				|
04F2 9F        SBC     A,A	;			  |	|				|
04F3 AB        XOR     E	;			  |	|				|
04F4 5F        LD      E,A	;			  |	|				|
04F5 7C        LD      A,H	;			  |	|				|
04F6 E601      AND     $01	;			  |	|				|
04F8 D601      SUB     $01	;			  |	|				|
04FA 9F        SBC     A,A	;			  |	|				|
04FB AB        XOR     E	;			  |	|				|
04FC 5F        LD      E,A	;			  |	|				|
04FD 7C        LD      A,H	;			  |	|				|
04FE E608      AND     $08	;			  |	|				|
0500 D601      SUB     $01	;			  |	|				|
0502 9F        SBC     A,A	;			  |	|				|
0503 AB        XOR     E	;			  |	|				|
0504 5F        LD      E,A	;			  |	|				|
0505 7C        LD      A,H	;			  |	|				|
0506 E680      AND     $80	;			  |	|				|
0508 D601      SUB     $01	;			  |	|				|
050A 9F        SBC     A,A	;			  |	|				|
050B AB        XOR     E	;			  |	|				|
050C 07        RLCA		;			  |	|				|
050D CB15      RL      L	;			  |	|				|
050F CB14      RL      H	;			  |	|				|
0511 10D6      DJNZ    $04E9	; ---> 8 loops -----> --->|	|				|
0513 D9        EXX		;				|				|
0514 23        INC     HL	; increment mem pointer		|				|
0515 1B        DEC     DE	; decrement loop counter	|				|
0516 7A        LD      A,D	;\ test if			|				|
0517 B3        OR      E	;/ DE=0000			|				|
0518 20CA      JR      NZ,$04E4	; ---> ---> 800h loops---> ---> |				|
051A D9        EXX	;									|
051B FD5E00    LD      E,(IY+$00) ; stored checksum lower 8 bits				|
051E FD5601    LD      D,(IY+$01) ; stored checksum upper 8 bits				|
0521 FD23      INC     IY	; increment checksum pointer					|
0523 FD23      INC     IY	; increment checksum pointer					|
0525 AF        XOR     A	; reset CY flag							|
0526 ED52      SBC     HL,DE	; compare computed checksum with stored checksum		|
0528 2004      JR      NZ,$052E	; ---> ---> --->|						|
052A DDCB00BE  RES     7,(IX+$00) ;		| if chksum ok, reset blinking on color pattern |
052E DD23      INC     IX	; <--- <--- <---| point to next cell in color pattern		|
0530 D9        EXX		;								|
0531 C1        POP     BC	; B = loop counter						|
0532 10A3      DJNZ    $04D7	; ---> 8 loops -----> ---> ---> ---> ---> ---> ---> ---> ---> ->|
0534 E1        POP     HL
0535 D9        EXX
0536 FF        RST     $38	; ################## END CHECKSUM ROUTINE ##########################	---@@@(21)0536:FF->C7 (RST 0)
				; ################## TAPE LOADING ROUTINE ##########################
0537 DD210080  LD      IX,$8000	; loading address of first half of BASIC
053B 37        SCF
053C CDE803    CALL    $03E8	; tape loading								---@@@(22)053E:03->13
053F 3008      JR      NC,$0549
0541 DD2100A0  LD      IX,$A000
0545 37        SCF
0546 CDE803    CALL    $03E8	; tape loading								---@@@(23)0548:03->13
0549 D20400    JP      NC,$0004	;									---@@@(24)054B:00->10
054C AF        XOR     A	; A = 00
054D 67        LD      H,A	;\load HL register
054E 6F        LD      L,A	;/with 0000 value (start addr in upcoming BASIC config)
054F C35100    JP      $0051	; ################## END TAPE LOADING ROUTINE ######################	---@@@(25)0551:00->10
;	;
;	;			  ################## START CP/M LOADING ROUTINE ####################
0552 DBFD      IN      A,($FD)	; read 1 byte from 8272 Data Register, it should be 80 (result of the
				; invalid command sent to 8272 by the instruction at 002A).
0554 FE80      CP      $80	; This tests whether 8272 present and properly reset.
0556 C20400    JP      NZ,$0004	; if not 80, restart execution from the beginning of the BOOT EPROM	---@@@(26)0558:00->10
0559 216105    LD      HL,$0561	; 0561 is the addr of the 3rd instruction after this one
055C 3E41      LD      A,$41	; "41" is to be written to 8255 Port C after next line is executed
055E C35100    JP      $0051	; (see comments for code at 0051)					---@@@(27)0560:00->10
;				; after the jump, "41" is written to 8255 Port C which means:
				; signal "O6" set to 1, "O5" set to 0, border color set to blue;
				; then bit 7 of register R is reset to 0 by instruction "LD R,A"
				; and configuration is changed to CP/M ("O6"=1). In this new config
				; execution starts from address stored in register HL previously.
				; The entire BOOT EPROM code was previously copied to beginning of DRAM#0
				; (see comments at 001D) and DRAM#0 is located at 0000 in CP/M config
				; so HL points now to exactly the next instruction below.
0561 3E01      LD      A,$01
0563 D3FE      OUT     ($FE),A	; write 01 to port C of 8255 which means:
;				; set border to blue, set signal "SO" to 0, "O5" to 0 (lower half
				; of VRAM displayed), "O6" to 0 (CPU access to DRAM#1 instead of VRAM)
0565 210000    LD      HL,$0000	;\
0568 1100F8    LD      DE,$F800	; | BOOT EPROM code is again relocated, this time
056B 010008    LD      BC,$0800	; | to F800-FFFF (top of RAM, end of DRAM#3)
056E EDB0      LDIR		;/  from this point on, addresses listed on the left side are actually added to F800
0570 C373FD    JP      $FD73	; this jump continues execution with exactly the next line (0573+F800=FD73)
0573 ED5E      IM      2	; ******* NOTE: THIS IS THE STACK BASE SET AT THE BEGINNING OF THIS BOOT EPROM *********
0575 21E8FF    LD      HL,$FFE8	; CTC interrupt table start address
0578 7C        LD      A,H	; upper half of CTC interrupt table start address (FF)...
0579 ED47      LD      I,A	; ...is stored in register I (see Z80 docs)
057B 7D        LD      A,L	; lower half of CTC interrupt table start address (E8)...
057C D3E3      OUT     ($E3),A	; ... is sent to CTC channel 0 (Enable Interrupt, Counter Mode, Prescaler=256,
				; Falling Edge, Pulse Trigger, No Time Const., Continue, Vector)
				; MEANING: Interrupt Vector being used by all 4 channels!!
				; Interrupt Vector = 11101cc0 where cc is the CTC channel.
				; requesting the interrupt. So vector for CTC0 = E8, CTC1 = EA, CTC2 = EC, CTC3 = EE
				; The upper half of addr table pointer is FF which means 07 within this BOOT EPROM.
				; Thus the vector table is at 07E8 (byte read), 07EC (sector read) in this BOOT EPROM.
057E 3EFF      LD      A,$FF	; data for CTC0 on next line: set CTC0 to counter mode and enable CTC0 interrupts
0580 D3E3      OUT     ($E3),A	; write FF to CTC channel 0 (Enable Interrupt, Counter Mode, Prescaler=256,
				; Rising Edge, CLK/TRG Pulse Starts Timer, Time Const. Follows, Reset, Control).
				; MEANING: Reset, Enable Interrupts for Channel 0, a Time Constant follows.
0582 3E01      LD      A,$01	; time constant for CTC0 on next line: generate INT for each byte transferred from 8272 to µP
0584 D3E3      OUT     ($E3),A	; write 01 to CTC channel 0
				; MEANING: Time Constant byte (=01, for 1 byte read).
0586 21E4FF    LD      HL,$FFE4	; address of the 2 args (6F, 01) of 8272 Specify command (for DD) on next line
				; These args specify Head Load/Unload times, Step Rate and choose Non-DMA mode,
				; (SRT=10 ms, HUT=240 ms, HLT=0 ms, Non-DMA)
0589 CD0BFF    CALL    $FF0B	; call CTC1+2_INIT (which also sends a Specify command)
058C 0604      LD      B,$04	; B as counter, 4 = nr of times to repeat the cycle below, for 4 possible FDDs
058E C5        PUSH    BC	; <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <----|
058F 010402    LD      BC,$0204	; Code for Sense Drive Status cmd (04) with 1 arg (B=02)		|
0592 CDBDFE    CALL    $FEBD	; call 8272_CMD	(run Sense Drive Status cmd to check if 8272 is ready)	|
0595 CDF9FE    CALL    $FEF9	; call 8272_READ (read command result into (FFD5))			|
0598 C1        POP     BC	;									|
0599 3AD5FF    LD      A,($FFD5); actual addr 07D5 in this BOOT EPROM (Sense Dr Stat result)		|
059C CB6F      BIT     5,A	; test bit 5 of it (READY)						|
059E 2016      JR      NZ,$05B6	; if bit 5 not zero (drive is READY), jump ahead to 05B6 ---> ---> ---> | ---> ->(FF95 has the nr.
05A0 2195FF    LD      HL,$FF95	; address of a data byte actually located at 0795 in this BOOT EPROM	|	|of first drive
05A3 34        INC     (HL)	; increment data byte (arg for Sense Drive Stat, increment drive no#)	|	|found ready)
05A4 10E8      DJNZ    $058E	; ---> ---> ---> ---> repeat cycle 4 times for all 4 drives --> ---> --->	|
				; if no FDD responding properly, switch back to startup cfg			|
05A6 F3        DI		; ################ CPM_TO_COBRA ##################				|
05A7 ED46      IM      0	;										|
05A9 AF        XOR     A	;										|
05AA ED47      LD      I,A	;										|
05AC 210400    LD      HL,$0004	;										|	---@@@(28)05AE:00->10
05AF 3EC1      LD      A,$C1	;										|
05B1 D3FE      OUT     ($FE),A	; write C1 to port C of 8255 which means:					|
				; set "SO" to 1, "O6" to 1, "O5" to 0, border color to blue			|
05B3 ED4F      LD      R,A	; set bit 7 of R to 1 ---> hardware config changes to startup config		|
05B5 E9        JP      (HL)	; jump address in the new config (beginning of this BOOT EPROM)			|
	;													|
				; ############# begin actual CP/M loading <--- <--- <--- <--- <--- <--- <--- <--|
05B6 010702    LD      BC,$0207	; 02 means 1 argument, 07 = opcode for 8272 Recalibrate command
05B9 CDBDFE    CALL    $FEBD	; call 8272_CMD (send Recalibrate cmd to 8272 w.arg at FF95)
05BC CD40FF    CALL    $FF40	; call 8272_SEEK_TEST (Sense Interrupt Status)
05BF CD31FF    CALL    $FF31	; call 8272_COND_SEEK (Seek track #2 + Sense Interrupt Status)
05C2 014A02    LD      BC,$024A	; 02 means 1 argument, 4A = opcode for 8272 Read ID command (in Double Density)
05C5 CDBDFE    CALL    $FEBD	; call 8272_CMD (send Read ID command in DD to 8272)
05C8 CDF9FE    CALL    $FEF9	; call 8272_READ (read command result into (FFD5-FFDB))
05CB 3AD5FF    LD      A,($FFD5); load first result byte of Read ID into register A
05CE E6C0      AND     $C0	; testing bits 6 and 7
05D0 2811      JR      Z,$05E3	; if they are 0 (no errors in DD), jump 7 lines below ---> ---> ---> ---->
05D2 21ACFF    LD      HL,$FFAC	; > if errors reading DD, FDD must be SD, copy SD params block from 07AC |
05D5 1199FF    LD      DE,$FF99	; > over cmd params block at 0799 within this BOOT EPROM code		 |
05D8 010A00    LD      BC,$000A	; > (to change future 8272 command params for Single Density).		 |
05DB EDB0      LDIR		; After this, (FF99)=02 means DD, 00 means SD (arg #5 of 8272 Read Data) |
05DD 21E6FF    LD      HL,$FFE6	; addr of the 2 args (BF, 17) of Specify command (for SD) on next line	 |
				; (SRT=5 ms, HUT=240 ms, HLT=22 ms, Non-DMA)				 |
05E0 CD0BFF    CALL    $FF0B	; call CTC1+2_INIT (which also sends a Specify command)			 |
05E3 3A99FF    LD      A,($FF99); <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <-----|
05E6 B7        OR      A	; test (FF99) if zero (initially 02, it is 02 if DD, 00 if SD)
05E7 0604      LD      B,$04	; B used as counter** 		if DD (read 4 sectors = 4 x 512 = 2048 bytes)
05E9 1E01      LD      E,$01	; index to locate in memory the byte for sector number to use next
05EB 2002      JR      NZ,$05EF	; if not SD  ---> --->|		B=04, C=(FFE7)=17 (the 2nd arg of Specify at 05E0)
05ED 0610      LD      B,$10	; B used as counter** | 	if SD (read 16 sectors = 16 x 128 = 2048 bytes)
05EF CD54FF    CALL    $FF54	; FDD_SECT_READ <-<---<  read 1 sector to mem starting at (FFD0-FFD1)=F400
05F2 1C        INC     E	; next sector to try  | E=1...4 for DD, E=1...10h for SD
05F3 10FA      DJNZ    $05EF	; ---> ---> ---> ---->| (FFA3-FFA6) for DD, (FFB6-FFC6) for SD
05F5 210000    LD      HL,$0000	;			(sectors 1,5,9,4 if DD, 01,07,0D,13,19,05,0B,11,17,03,09,0F,15,02,08,0E if SD)
05F8 22D0FF    LD      ($FFD0),HL ; (FFD0)&(FFD1) = 0000 = new start address for storage of data read from disk
05FB 2100F4    LD      HL,$F400
05FE E5        PUSH    HL
05FF E1        POP     HL	; <--- jump here from 067D <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <--<--|
0600 0640      LD      B,$40	; 40h=64 directory entries to search (2048 bytes)					|
0602 7E        LD      A,(HL)	; <--- <--- <--- <--- <--- <--- <--- <--| search max 64 (40h) times			|
0603 B7        OR      A	;					| in steps of 32 (20h) bytes (=1 dir entry)	|
0604 2014      JR      NZ,$061A	; ---> ---> ---> ------>  not 00 ?	| for a 00 byte (meaning USER 0) in data read	|
0606 C5        PUSH    BC	; * 40xx		|		| from FDD. If no 00 byte found after 64 tries,	|
0607 E5        PUSH    HL	; **F400+(20*count)	|		| reset BOOT EPROM				|
0608 110900    LD      DE,$0009	;			|		| If 00 byte found, go 9 bytes after it and	|
060B 19        ADD     HL,DE	; HL=F409+(20*count)	|		| test to see if the 3 next bytes (filename	|
060C EB        EX      DE,HL	; HL=0009, DE=F409+...	|		| extension) contain "SYS" in their lower 7 bits|
060D 21DEFF    LD      HL,$FFDE	; HL=FFDE		|		| If they do, then continue executing code after|
0610 0603      LD      B,$03	; 3 chars of a fname ext| to check	| this loop. If they are not, reset BOOT EPROM	|
0612 1A        LD      A,(DE)	; A=(F409) <--- <--- <-	| <-----|	|						|
0613 E67F      AND     $7F	;			|	|	|						|
0615 BE        CP      (HL)	; cmp sect w signature	| (SYS)	|	|						|
0616 280A      JR      Z,$0622	; ---> ---> --->	|	|	|						|
0618 E1        POP     HL	; **		|	|	|	|						|
0619 C1        POP     BC	; *		|	|	|	|						|
061A 112000    LD      DE,$0020	; <--- <--- <--	| <-----|	|	|						|
061D 19        ADD     HL,DE	; fwd 20 bytes	|		|	|						|
061E 10E2      DJNZ    $0602	; ---> ---> --->|---> ---> ---> ---> --->						|
0620 1884      JR      $05A6	; CPM_TO_COBRA  |		|							|
0622 13        INC     DE	; <--- <--- <---|		|							|
0623 23        INC     HL	;				|							|
0624 10EC      DJNZ    $0612	; ---> ---> ---> ---> ---> ---->|							|
0626 D1        POP     DE	; **DE=F400										|
0627 211000    LD      HL,$0010	;					If "S", "Y", "S" or D3, D9, D3 found, go 16	|
062A 19        ADD     HL,DE	; HL=F410				(10h) bytes after the 00 previously found	|
062B 1100FC    LD      DE,$FC00	; DE=FC00				before "SYS" and copy 16 (10h) bytes to FC00	|
062E D5        PUSH    DE	; (SP)=FC00				These bytes are the allocation table for the	|
062F 011000    LD      BC,$0010	;					current directory entry				|
0632 EDB0      LDIR		; 16 bytes from F410 to FC00. After this, HL=F420, DE=FC10				|
0634 E3        EX      (SP),HL	; (SP)=F420=addr of next entry, HL=FC00=addr of allocation table			|
0635 7E        LD      A,(HL)	; low byte of block address (07) for CHRIS.SYS or Kryss.SYS				|
0636 E5        PUSH    HL	; (SP)=FC00 <--- <--- <--- <--- <--- <--- <--- <--- <--- <---- <--- <--- <------|	|
0637 2600      LD      H,$00	;										|	|
0639 6F        LD      L,A	; low byte of block address (07) for CHRIS.SYS or Kryss.SYS			|	|
063A 01FF03    LD      BC,$03FF	; repeat next loop 3 times, C=FF						|	|
063D CB25      SLA     L	; <--- <---| assume SD (8 sectors/block) and compute absolute sector addr	|	| <-- Block size is assumed to be 1K but for DD it is actually 2K.
063F CB14      RL      H	; HL=HL*2  | as (block_addr*8) and adjust later (/4) if DD (2 sectors/block)	|	|     The trick is that the block number used is mangled to give
0641 10FA      DJNZ    $063D	; ---> --->|	(00111000=38h)							|	|     the correct target sector on current DD disks
0643 23        INC     HL	; HL=block addr*8+1=sect_addr_SD (sector numbers start at 1) (00111001=39h)	|	|
0644 ED5B9FFF  LD      DE,($FF9F) ; 256B Sectors/cyl=36 (24h) if DD, 128B Sectors/cyl=26 (1Ah) if SD		|	| <-- DD sector size used here
0648 0C        INC     C	; C = 00 for start <--- <--- <--- <--- <--					|	|     is different than real size (512B)
0649 ED52      SBC     HL,DE	; (sect_addr_SD) minus (sectors/cyl)	 |					|	|     used on today's CoBra disks
064B 30FB      JR      NC,$0648	; ---> ---> ---> ---> ---> ---> ---> --->|					|	|     (this code is old & translation
064D 19        ADD     HL,DE	; >> HL=(sect_addr_SD) mod (sect/cyl)=sect#_on_cyl_SD (0015 if DD, 0005 if SD)	|	|      algorithm was not updated, instead
;				; and C=(sect_addr_SD)/(sect/cyl)=cyl#		(01 if DD or 02 if SD)		|	|      the computing of data location was
064E 3A99FF    LD      A,($FF99); arg #4 of 8272 command (N=log2(bytes/sector)-log2(128))			|	|      just mangled to give correct result)
0651 B7        OR      A	; test if 00 (Single Density)							|	|
0652 0608      LD      B,$08	; 8 loops if SD									|	|
0654 2808      JR      Z,$065E	; if Single Density (L=05) ---->|						|	|
0656 0602      LD      B,$02	; 2 loops if DD			| adjust sect#_on_cyl for Double Density	|	|
0658 2D        DEC     L	; ] L=L-1			| x MOD y = x - y * int(x/y) = expr		|	|
0659 CB3D      SRL     L	; ] L=L/2			| then expr/4 = x/4 - y/4 * int(x/y) so here	|	|
065B CB3D      SRL     L	; ] L=L/2			| (adr*8) mod 36=adr*8-36*[(adr*8)/36]=expr	|	|
065D 2C        INC     L	; ] L=(sect#_on_cyl-1)/4+1=06	| and expr/4=adr*2-9*[(adr*2)/9]=(adr*2) mod 9	|	|
065E 3E02      LD      A,$02	; <--- <--- <--- <--- <--- <----| so dividing by 4 gives the correct adjustment	|	|
0660 81        ADD     A,C	; cyl# + 2 because block numbers start on cyl #2 (03 if DD or 04 if SD)		|	|
0661 57        LD      D,A	; track# = 03 or 04 (DD or SD)							|	|
0662 5D        LD      E,L	; sect# = 06 or 05 (DD or SD)							|	|
0663 7A        LD      A,D	; <--- <--- 2 loops if DD, 8 loops if SD  <--- <--- <--- <---|			|	| read from disk to mem starting at 0000
0664 32D4FF    LD      ($FFD4),A; (FFD4)=track number in 8272_COND_SEEK			     | 03...04 (if DD)	|	| if DD read trk#3 sect#3 and trk#4 sect#7
0667 CD54FF    CALL    $FF54	; call FDD_SECT_READ	E=06,07	-->sect	3,7		     |			|	|
066A 2A9AFF    LD      HL,($FF9A) ; L=final sector nr on a track (EOT), arg #6 of 8272 cmd   |			|	|
066D 23        INC     HL	; L=0A or 1B						     |			|	|
066E 1C        INC     E	; used as index to determine sector no.			     | 06...07		|	|
066F 7B        LD      A,E	;							     |			|	|
0670 BD        CP      L	; comp index w max. sector no				     |			|	|
0671 3803      JR      C,$0676	;				--> --->|		     |			|	|
0673 14        INC     D	;					|		     | 04...0B (if DD)	|	|
0674 1E01      LD      E,$01	;					|		     |			|	|
0676 10EB      DJNZ    $0663	; ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> --->|			|	|
0678 E1        POP     HL	; FC00										|	|
0679 23        INC     HL	; FC01										|	|
067A 3E0F      LD      A,$0F	;										|	|
067C A5        AND     L	; 01										|	|
067D 2880      JR      Z,$05FF	; no jump most likely	 --> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> --->|
067F 7E        LD      A,(HL)	; (FC01)=00 most likely								|
0680 B7        OR      A	;										|
0681 20B3      JR      NZ,$0636	; no jump most likely	 ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---->| 
0683 F3        DI
0684 210000    LD      HL,$0000
0687 7E        LD      A,(HL)
0688 FEF3      CP      $F3	; test if first byte of presumed CP/M loader code is F3 (should be 00)
068A D9        EXX
068B 214300    LD      HL,$0043
068E CAAFFD    JP      Z,$FDAF	; if it is, go to CPM_TO_COBRA
0691 D9        EXX
0692 E9        JP      (HL)	; ########## End of actual CP/M loading ###########

0693 08        EX      AF,AF'	; ############## CTC0 (Byte Read) Interrupt Service Routine ####################
0694 3E7F      LD      A,$7F	; control word for CTC channel 1 (in next instruction)
0696 D3EB      OUT     ($EB),A	; write 7F to CTC channel 1 (Disable Interrupt, Counter Mode, Prescaler=256,
				; Rising Edge, Pulse Trigger, Time Const. Follows, Reset, Control)
				; MEANING: Reset Channel 1, resume operation after loading a time constant.
0698 3A9EFF    LD      A,($FF9E); load A with data byte from address 079E (00)
069B D3EB      OUT     ($EB),A	; write time constant byte (00) to CTC channel 1
069D 08        EX      AF,AF'
069E FB        EI		; --------- CTC Channel 1 & 3 Interrupt service routine (does nothing) ---------
069F ED4D      RETI		; ##############################################################################

06A1 EDA2      INI		; ############## Alternate CTC0 (Byte Read) Interrupt Service Routine ##########
06A3 FB        EI		;
06A4 ED4D      RETI		;
				; ############## CTC2 (Sector Read) Interrupt Service Routine ##################
06A6 22D2FF    LD      ($FFD2),HL ; HL contains the addr of the last byte read from disk by 8272_CMD1 plus 1
06A9 2193FE    LD      HL,$FE93	; FE93 is the initial CTC0 interrupt routine address stored at FFE8
06AC 22E8FF    LD      ($FFE8),HL ; restore initial CTC0 interrupt routine address stored at FFE8
06AF 0E00      LD      C,$00	; C was used to store the port address for 8272 Data Register (FD)
06B1 FB        EI		;
06B2 ED4D      RETI		;
;				  ##################### 8272_POLL ##############################
06B4 DBF5      IN      A,($F5)	; read 8272 Status Register			| this routine polls the 8272 Status Register
06B6 CB7F      BIT     7,A	; test bit 7 (RQM)				| until 8272 is ready to send or receive
06B8 28FA      JR      Z,$06B4	; if bit 7 = 0 read 8272 Status Register again	| data to or from the CPU. When ready (RQM=1)
06BA CB77      BIT     6,A	; test bit 6					| bit 6 is tested (DIO, 0=send/1=receive)
06BC C9        RET		;
;				  ##################### 8272_CMD ###############################
06BD 2195FF    LD      HL,$FF95	; (command args addr=0795)
06C0 CDB4FE    CALL    $FEB4	; call 8272_POLL ------ 8272_CMD_HL --------  <--- <--- <--- <---|
06C3 C2A6FD    JP      NZ,$FDA6	; jump to CPM_TO_COBRA, if data out of 8272			 |
06C6 79        LD      A,C	; (C = opcode for 8272 command)					 |
06C7 D3FD      OUT     ($FD),A	; send opcode to 8272 Data Register				 |
06C9 4E        LD      C,(HL)	; load C with command arg from address (HL)			 |
06CA 23        INC     HL	; increment pointer to command args				 |
06CB 10F3      DJNZ    $06C0	; ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> --->
06CD C9        RET
;				  ##################### 8272_CMD1 ##############################
06CE 1195FF    LD      DE,$FF95	; start address for 8272 command arguments
06D1 21A1FE    LD      HL,$FEA1	; address of another interrupt routine (06A1 in the BOOT EPROM)
06D4 22E8FF    LD      ($FFE8),HL ; replace the CTC0 interrupt routine address in address table
06D7 2AD0FF    LD      HL,($FFD0) ; initially (FFD0)=00, (FFD1)=F4, so HL=F400
06DA 1803      JR      $06DF	; ---> --->|
06DC 1A        LD      A,(DE)	; <--- <-- | <--- <--- <--- <--- <--- <--- <----|
06DD 13        INC     DE	;	   V					|
06DE 4F        LD      C,A	;	   |save A in C bcoz A used by 8272_POLL|
06DF CDB4FE    CALL    $FEB4	; <--- <---| 8272_POLL				|
06E2 C2A6FD    JP      NZ,$FDA6	; if not ready for new command, CPM_TO_COBRA	|
06E5 79        LD      A,C	;						|
06E6 0EFD      LD      C,$FD	;						|
06E8 ED79      OUT     (C),A	; send contents of A to 8272 Data Register	|
06EA 10F0      DJNZ    $06DC	;  ---> ---> ---> ---> ---> ---> ---> ---> ---->|
;				; At this point, B=00, C=FD, HL=F400. The next instruction halts the CPU, waiting
				; for an interrupt from 8272 after each byte was read from disk.
				; The interrupt routine at FEA1 then writes the I/O bytes from (C=FD) to memory starting at (HL)
				; which is F400. HL is a memory pointer and B is a counter for this process (00-FF).
				; (B decremented & HL incremented by the INI instruction in the CTC0 alternate int. routine)
06EC 76        HALT		; wait for next interrupt <--- <--- <--- <---|
06ED DBF5      IN      A,($F5)	; read 8272 Status Register		     |
06EF E620      AND     $20	; test bit 5 (Non-DMA Execution Phase)	     |
06F1 20F9      JR      NZ,$06EC	; if "1" (Execution not finished) ---> ----->|
06F3 2193FE    LD      HL,$FE93	; initial address of the CTC0 interrupt routine in the interrupt addr table
06F6 22E8FF    LD      ($FFE8),HL ; restore initial address of the CTC0 interrupt routine in the interrupt addr table

06F9 21D5FF    LD      HL,$FFD5	; ##################### 8272_READ ###############################
06FC 0608      LD      B,$08	; ###     reads max 8 bytes from 8272 into memory at FFD5     ###
06FE CDB4FE    CALL    $FEB4	; 8272_POLL <---- <---- <---- <---- <---- <---- <---- <---- <---|
0701 C8        RET     Z	; return if data to go from CPU into 8272 (normal return)	|
0702 DBFD      IN      A,($FD)	; read from 8272 Data Register					|
0704 77        LD      (HL),A	; store data at address pointed to by HL			|
0705 23        INC     HL	; increment pointer						|
0706 10F6      DJNZ    $06FE	; if B not zero ---> ---> ---> ---> ---> ---> ---> ---> ---> --->
0708 C3A6FD    JP      $FDA6	; ---> CPM_TO_COBRA

070B F3        DI		; ##################### CTC1+2_INIT ###########################
070C 3E7F      LD      A,$7F	; control word for CTC channel 1 (in next instruction)
070E D3EB      OUT     ($EB),A	; write 7F to CTC channel 1 (Disable Interrupt, Counter Mode, Presc=256,
				; Rising Edge, Pulse Trigger, Time Const. Follows, Reset, Control)
				; MEANING: Reset Channel 1, resume operation after loading a time const.
0710 3A9EFF    LD      A,($FF9E); load A with data byte from address 079E (00)
0713 D3EB      OUT     ($EB),A	; write time constant byte (00) to CTC channel 1
0715 3EFF      LD      A,$FF	; control word for CTC channel 2 (in next instruction)
0717 D3F3      OUT     ($F3),A	; write FF to CTC channel 2 (Enable Interrupt, Counter Mode, Prescaler=256,
				; Rising Edge, Pulse Trigger, Time Const. Follows, Reset, Control)
				; MEANING: Reset Channel 2, resume operation after loading a time constant.
0719 3A9DFF    LD      A,($FF9D); load A with data byte from address 079D (02)
071C D3F3      OUT     ($F3),A	; write time constant byte (02) to CTC channel 2
071E FB        EI		;
071F 010303    LD      BC,$0303	; B=nr of args for 8272 command + 1, C=opcode for 8272 "Specify" command
0722 189C      JR      $06C0	; ---> ---> jump to 8272_CMD_HL ---> --->

;				  ##################### 8272_CMD_SIS ##########################
0724 010801    LD      BC,$0108	; 01 means no arguments (zero), 08 = opcode for 8272 Sense Interrupt Status
0727 CDBDFE    CALL    $FEBD	; call 8272_CMD, send Sense Interrupt Status command to 8272
072A CDF9FE    CALL    $FEF9	; call 8272_READ, read command result (2 bytes) into memory at FFD5-FFD6
072D 3AD5FF    LD      A,($FFD5); load command result byte 1 (ST0) into register A
0730 C9        RET     
;				  ##################### 8272_COND_SEEK ########################
0731 3AD4FF    LD      A,($FFD4); \  Compare (FFD4) (initially 02) - (FFD4)=track to seek
0734 2196FF    LD      HL,$FF96	;  \ with (FF96) (initially 00)    - (FF96)=current track
0737 BE        CP      (HL)	;  / and
0738 C8        RET     Z	; /  return if equal
0739 77        LD      (HL),A	; replace (FF96) with (FFD4)
073A 010F03    LD      BC,$030F	; Seek command for 8272, with 2 arguments (drive, cyl=2), to be sent in next instruction
073D CDBDFE    CALL    $FEBD	; call 8272_CMD
				; --------------------- 8272_SEEK_TEST ------------------------
0740 CD24FF    CALL    $FF24	; call 8272_CMD_SIS and get result in A
				; (*** Sense Interrupt Status is mandatory after Seek or Recalibrate ***)
0743 CB6F      BIT     5,A	; test bit 5 (Seek End)
0745 28F9      JR      Z,$0740	; if Seek not finished, go back 2 lines above (??? should it be 4 lines ???)
0747 E6D8      AND     $D8	; check if errors or drive not ready
0749 C2A6FD    JP      NZ,$FDA6	; ---> if so, jump to CPM_TO_COBRA
074C CD24FF    CALL    $FF24	; 8272_CMD_SIS - send Sense Interrupt Status command to 8272 and get result in A <--
074F FE80      CP      $80	; check if Invalid Command Issue						   |
0751 C8        RET     Z	; return if so									   |
0752 18F8      JR      $074C	; go back 3 lines above ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> --->|

				; ##################### FDD_SECT_READ ###############################
0754 C5        PUSH    BC	; 0417 > BC and DE are saved on stack so their contents
0755 D5        PUSH    DE	; 0001 > can be restored at the end of this routine
0756 CD31FF    CALL    $FF31	; call 8272_COND_SEEK
0759 1600      LD      D,$00	;
075B 2AA1FF    LD      HL,($FFA1) ; (FFA1)=A2, (FFA2)=FF for DD    or  (FFA1)=B5, (FFA2)=FF for SD
075E 19        ADD     HL,DE	; result HL=FFA2+0001=FFA3 for DD or  HL=FFB5+0001=FFB6 for SD
075F 7E        LD      A,(HL)	; (FFA3)=01 (for DD) or (FFB5)=01 (for SD)
0760 3298FF    LD      ($FF98),A; (0798) is arg #4 of Read Data (Sector number)
0763 060A      LD      B,$0A	; 10 loops to do next			;
0765 C5        PUSH    BC	; BC=0A17 (B used as counter**)	 <--- <--- <--- <--- <--- <--- <--- <---|
0766 3A99FF    LD      A,($FF99); (FF99)=02 or 00							|
0769 B7        OR      A	; (FF99) can be either 02 (initial val) or 00 if Read ID at 05C5 gave errors (see lines 05D2-05DB)
076A 010609    LD      BC,$0906	; 06 = opcode for 8272 Read Data command with 8 args starting at FF95 (Single Density, MFM=0)
076D 2802      JR      Z,$0771	; skip next line if A=00 (Read Data in Single Density)			|
076F CBF1      SET     6,C	; BC=0946 meaning 8272 Read Data command with 8 args starting at FF95	| bit 6 is MFM bit, MFM=1 means
;				; 46 = opcode for <Read Data - MT=0 (single side), MFM=1 (DD), no Skip> | Read Data in Double Density
				; **arguments:	- Side 0 drive found Ready				|
				; ---> @FF96 >>	- Cyl 00  (C=00)					|
				;		- Head 00 (H=00)					|
				; ---> @FF98 >>	- Sector Number 01 (R=01)				|
				; ---> @FF99 >>	- 512 bytes/sector (N=02) or 128 if N=00 (Singl Density)|
				;		- EOT=09 (End Of Track Sector Number)			| <-- 09 if DD, 1A if SD
				;		- GPL=2A (Gap 3 Length)					| <-- 2A if DD, 07 if SD
				;		- DTL=FF (Data Length, has no meaning for N != 00)	| <-- FF if DD, 80 if SD
0771 CDCEFE    CALL    $FECE	; call 8272_CMD1, run Read Data command					| <-- data being read is saved at address stored in (FFD0-FFD1)
0774 AF        XOR     A	; A=0	;								|
0775 B1        OR      C	; C=00 after 8272_CMD1 (CTC2 interrupt sets C to 00)			|
0776 C1        POP     BC	; BC=0A17 (B used as counter**)						|
0777 200E      JR      NZ,$0787	; if C not zero, jump ---> ---> ---> -->|				|
0779 21D7FF    LD      HL,$FFD7	; (FFD7)=ST2 (result byte #3)		|				|
077C 7E        LD      A,(HL)	;					|				|
077D 2B        DEC     HL	; (FFD6)=ST1 (result byte #2)		|				|
077E B6        OR      (HL)	;					|				|
077F 2006      JR      NZ,$0787	; if errors ST1 or ST0 != 00 ---> ----->|				|
0781 2B        DEC     HL	; (FFD5)=ST0 (result byte #1)		|				|
0782 7E        LD      A,(HL)	;					|				|
0783 E6D8      AND     $D8	; check if err or drv not Ready 	|				|
0785 2805      JR      Z,$078C	; if no error, jump ---> ---> --->|	|				|
0787 10DC      DJNZ    $0765	; ---> ---> ---> ---> ---> ---> ---> -->| -----> ---> ---> ---> ---> --->
0789 C3A6FD    JP      $FDA6	; CPM_TO_COBRA			  |
;								  |
078C 2AD2FF    LD      HL,($FFD2) ; <--- <--- <--- <--- <--- <----| CTC2 int. routine saved addr for next sector into (FFD2),(FFD3)
078F 22D0FF    LD      ($FFD0),HL ; update start mem address for next sector read from FDD
0792 D1        POP     DE	; > restore BC and DE to the values they had
0793 C1        POP     BC	; > before execution of this routine
0794 C9        RET		; #################### END CP/M LOADING ROUTINE ####################

;				; ############## BEGIN OF DATA BLOCK ################
0795 00        DB      $00	;\  <<<--- arg #1 of max. 8 (Side and drive number)
0796 00        DB      $00	; | <<<--- arg #2 of 8272 Read Data (current track number)
0797 00        DB      $00	; | <<<--- arg #3 of 8272 Read Data (head selected)
0798 01        DB      $01	; | <<<--- arg #4 of 8272 Read Data (Sector number)
0799 02        DB      $02	;*| <<<--- arg #5 of 8272 Read Data (N=02, Double Density)		*
079A 09        DB      $09	; | <<<--- arg #6 of 8272 Read Data (EOT, final sector nr on track)	|
079B 2A        DB      $2A	; | <<<--- arg #7							| Double Density
079C FF        DB      $FF	;/  <<<--- arg #8							|
079D 02        DB      $02	; CTC Channel 2 Time Constant - for Double Density \  2 x 256 = 512	| parameters
079E 00        DB      $00	; CTC Channel 1 Time Constant - for Double Density / (DD sector size)	|
079F 24        DB      $24	;   <<<--- No of sectors per cylinder in Double Density			| block
07A0 00        DB      $00	;									|
07A1 A2        DB      $A2	;   <<<---| base pointer to beginning of translation table		|
07A2 FF        DB      $FF	;*  <<<---| with DD sector numbers (next 9 bytes)			*
07A3 01        DB      $01	; N
07A4 05        DB      $05	; N
07A5 09        DB      $09	; N  9 sector numbers (01...09)
07A6 04        DB      $04	; N  to try with
07A7 08        DB      $08	; N  the Read Data
07A8 03        DB      $03	; N  command if
07A9 07        DB      $07	; N  Double Density
07AA 02        DB      $02	; N
07AB 06        DB      $06	; N
07AC 00        DB      $00	;*| <<<--- arg #5 of 8272 Read Data (N=00, Single Density)		*
07AD 1A        DB      $1A	; | <<<--- arg #6 of 8272 Read Data (EOT, final sector nr on track)	|
07AE 07        DB      $07	; | <<<--- arg #7							| Single Density
07AF 80        DB      $80	;/  <<<--- arg #8							|
07B0 01        DB      $01	; CTC Channel 2 Time Constant - for Single Density \  1 x 128 = 128	| parameters
07B1 80        DB      $80	; CTC Channel 1 Time Constant - for Single Density / (SD sector size)	|
07B2 1A        DB      $1A	;   <<<--- No of sectors per cylinder in Single Density			| block
07B3 00        DB      $00	;									|
07B4 B5        DB      $B5	;   <<<---| base pointer to beginning of translation table		|
07B5 FF        DB      $FF	;*  <<<---| with SD sector numbers (next 26 bytes)			*
07B6 01        DB      $01	; N
07B7 07        DB      $07	; N
07B8 0D        DB      $0D	; N
07B9 13        DB      $13	; N
07BA 19        DB      $19	; N
07BB 05        DB      $05	; N
07BC 0B        DB      $0B	; N
07BD 11        DB      $11	; N
07BE 17        DB      $17	; N
07BF 03        DB      $03	; N
07C0 09        DB      $09	; N
07C1 0F        DB      $0F	; N  26 sector numbers (01...1A)
07C2 15        DB      $15	; N  to try with
07C3 02        DB      $02	; N  the Read Data
07C4 08        DB      $08	; N  command if
07C5 0E        DB      $0E	; N  Single Density
07C6 14        DB      $14	; N
07C7 1A        DB      $1A	; N
07C8 06        DB      $06	; N
07C9 0C        DB      $0C	; N
07CA 12        DB      $12	; N
07CB 18        DB      $18	; N
07CC 04        DB      $04	; N
07CD 0A        DB      $0A	; N
07CE 10        DB      $10	; N
07CF 16        DB      $16	; N
07D0 00        DB      $00	; \these 2 bytes contain the start address for last sector
07D1 F4        DB      $F4	; /read from floppy disk (F400) used by 8272_CMD1
07D2 00        DB      $00	; \these 2 bytes contain the start address for next sector
07D3 F4        DB      $F4	; /to be read from floppy disk (see CTC2 Int. Routine & end of FDD_SECT_READ)
07D4 02        DB      $02	; <<<--- track to seek in next command
07D5 41        DB      $41	; A	\  storage area
07D6 52        DB      $52	; R	 | for result data
07D7 4D        DB      $4D	; M	 | from 8272_READ
07D8 41        DB      $41	; A	 | (7 bytes)
07D9 26        DB      $26	; &	 |
07DA 24        DB      $24	; $	 |
07DB 4F        DB      $4F	; O	/
07DC 46        DB      $46	; F
07DD 54        DB      $54	; T
07DE 53        DB      $53	; S
07DF 59        DB      $59	; Y
07E0 53        DB      $53	; S
07E1 38        DB      $38	; 8
07E2 30        DB      $30	; 0
07E3 6B        DB      $6B	; k
07E4 6F        DB      $6F	; o \ arguments for a "Specify" command: Step Rate Time = B (5 ms),
07E5 01        DB      $01	;   / Head Unload Time = F (240 ms), Head Load Time = 0B (22 ms), Non-DMA
07E6 BF        DB      $BF	;\ arguments for a "Specify" command: Step Rate Time = B (5 ms),
07E7 17        DB      $17	;/ Head Unload Time = F (240 ms), Head Load Time = 0B (22 ms), Non-DMA
07E8 93        DB      $93	;\ interrupt routine address = FE93 (0693 within this BOOT EPROM)
07E9 FE        DB      $FE	;/ for CTC Channel 0 (Byte Read)
07EA 9E        DB      $9E	;\ interrupt routine address = FE9E (069E within this BOOT EPROM)
07EB FE        DB      $FE	;/ for CTC Channel 1 (Not used)
07EC A6        DB      $A6	;\ interrupt routine address = FEA6 (06A6 within this BOOT EPROM)
07ED FE        DB      $FE	;/ for CTC Channel 2 (Sector Read)
07EE 9E        DB      $9E	;\ interrupt routine address = FE9E (069E within this BOOT EPROM)
07EF FE        DB      $FE	;/ for CTC Channel 3 (Not used)
;				; ################ END OF DATA BLOCK ################
;
;				  ################ START OF BASIC LOADING ROUTINE #################
07F0 3E0F      LD      A,$0F	; control word to be written to 8255 meaning "set bit 7 of Port C"
07F2 D3DF      OUT     ($DF),A	; which is signal "SO" which drives pin A14 of BASIC EPROM (>= 32K)
;				  that means the BASIC EPROM must have BASIC code at 4000 (or C000)
;				  ################ START OF OPUS LOADING ROUTINE ##################
07F4 210000    LD      HL,$0000	; jump address after hardware configuration change
07F7 D9        EXX
07F8 FF        RST     $38	; jump to the BASIC CONFIGURATION ROUTINE					---@@@(29)07F8:FF->C3
07F9 FF        RST     38	;										---@@@(30)07F9:FF->38
07FA FF        RST     38	;										---@@@(31)07FA:FF->10
07FB FF        RST     38
07FC FF        RST     38
07FD FF        RST     38
07FE FF        RST     38
07FF FF        RST     38